import pygame
import sqlite3
import datetime
from pygame.locals import *
import os
import sys

# 初始化Pygame
pygame.init()
# 启用中文输入法支持
os.environ['SDL_IME_SHOW_UI'] = '1'
os.environ['SDL_IME_ENABLE'] = '1'
pygame.key.start_text_input()

# 屏幕设置
SCREEN_WIDTH = 1000
SCREEN_HEIGHT = 700
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("个人任务管理器")

# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GRAY = (230, 230, 230)
LIGHT_GRAY = (240, 240, 240)
DARK_GRAY = (100, 100, 100)
RED = (255, 59, 48)
ORANGE = (255, 149, 0)
GREEN = (52, 199, 89)
BLUE = (0, 122, 255)
LIGHT_BLUE = (90, 200, 250)

# 字体设置 - 使用微软雅黑确保中文显示正常
try:
    font_path = "C:/Windows/Fonts/msyh.ttc"  # 微软雅黑字体路径
    if not os.path.exists(font_path):
        font_path = pygame.font.get_default_font()
        print(f"默认字体路径: {font_path}")
    
    FONT_SMALL = pygame.font.Font(font_path, 14)
    FONT_MEDIUM = pygame.font.Font(font_path, 18)
    FONT_LARGE = pygame.font.Font(font_path, 24)
    FONT_TITLE = pygame.font.Font(font_path, 32)
except Exception as e:
    print(f"字体加载错误: {e}")
    # 回退到系统默认字体
    FONT_SMALL = pygame.font.SysFont("microsoftyahei", 14)
    FONT_MEDIUM = pygame.font.SysFont("microsoftyahei", 18)
    FONT_LARGE = pygame.font.SysFont("microsoftyahei", 24)
    FONT_TITLE = pygame.font.SysFont("microsoftyahei", 32)

# 数据库操作
def init_database():
    """初始化数据库连接和表结构"""
    conn = sqlite3.connect('tasks.db')
    cursor = conn.cursor()
    cursor.execute('''
    CREATE TABLE IF NOT EXISTS tasks (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        title TEXT NOT NULL,
        description TEXT,
        due_date TEXT,
        priority INTEGER DEFAULT 3,
        completed BOOLEAN DEFAULT 0
    )
    ''')
    conn.commit()
    conn.close()

def get_all_tasks(sort_by="priority", filter_completed=None):
    """获取所有任务，可按条件排序和筛选"""
    conn = sqlite3.connect('tasks.db')
    cursor = conn.cursor()
    
    query = "SELECT * FROM tasks"
    params = []
    
    # 筛选条件
    if filter_completed is not None:
        query += " WHERE completed = ?"
        params.append(filter_completed)
    
    # 排序条件
    if sort_by == "priority":
        query += " ORDER BY priority ASC, due_date ASC"
    elif sort_by == "due_date":
        query += " ORDER BY due_date ASC, priority ASC"
    
    cursor.execute(query, params)
    tasks = cursor.fetchall()
    conn.close()
    return tasks

def add_task(title, description, due_date, priority):
    """添加新任务"""
    conn = sqlite3.connect('tasks.db')
    cursor = conn.cursor()
    cursor.execute(
        "INSERT INTO tasks (title, description, due_date, priority, completed) VALUES (?, ?, ?, ?, 0)",
        (title, description, due_date, priority)
    )
    conn.commit()
    conn.close()

def update_task(task_id, title, description, due_date, priority, completed):
    """更新任务信息"""
    conn = sqlite3.connect('tasks.db')
    cursor = conn.cursor()
    cursor.execute(
        "UPDATE tasks SET title=?, description=?, due_date=?, priority=?, completed=? WHERE id=?",
        (title, description, due_date, priority, completed, task_id)
    )
    conn.commit()
    conn.close()

def delete_task(task_id):
    """删除任务"""
    conn = sqlite3.connect('tasks.db')
    cursor = conn.cursor()
    cursor.execute("DELETE FROM tasks WHERE id=?", (task_id,))
    conn.commit()
    conn.close()

def toggle_task_status(task_id, completed):
    """切换任务完成状态"""
    conn = sqlite3.connect('tasks.db')
    cursor = conn.cursor()
    cursor.execute("UPDATE tasks SET completed=? WHERE id=?", (completed, task_id))
    conn.commit()
    conn.close()

def get_task_stats():
    """获取任务统计信息"""
    conn = sqlite3.connect('tasks.db')
    cursor = conn.cursor()
    
    # 总任务数
    cursor.execute("SELECT COUNT(*) FROM tasks")
    total = cursor.fetchone()[0]
    
    # 已完成任务数
    cursor.execute("SELECT COUNT(*) FROM tasks WHERE completed=1")
    completed = cursor.fetchone()[0]
    
    # 未完成任务数
    cursor.execute("SELECT COUNT(*) FROM tasks WHERE completed=0")
    pending = cursor.fetchone()[0]
    
    # 高优先级未完成任务
    cursor.execute("SELECT COUNT(*) FROM tasks WHERE completed=0 AND priority=1")
    high_priority = cursor.fetchone()[0]
    
    conn.close()
    return {
        "total": total,
        "completed": completed,
        "pending": pending,
        "high_priority": high_priority
    }

# UI组件
class Button:
    def __init__(self, x, y, width, height, text, color, hover_color, text_color=BLACK, font=FONT_MEDIUM, border_radius=10):
        self.rect = pygame.Rect(x, y, width, height)
        self.text = text
        self.color = color
        self.hover_color = hover_color
        self.text_color = text_color
        self.font = font
        self.border_radius = border_radius
        self.is_hovered = False

    def draw(self, surface):
        color = self.hover_color if self.is_hovered else self.color
        pygame.draw.rect(surface, color, self.rect, border_radius=self.border_radius)
        
        text_surface = self.font.render(self.text, True, self.text_color)
        text_rect = text_surface.get_rect(center=self.rect.center)
        surface.blit(text_surface, text_rect)

    def check_hover(self, pos):
        self.is_hovered = self.rect.collidepoint(pos)
        return self.is_hovered

    def is_clicked(self, pos, event):
        if event.type == MOUSEBUTTONDOWN and event.button == 1:
            return self.rect.collidepoint(pos)
        return False

class InputBox:
    def __init__(self, x, y, width, height, text='', placeholder='', font=FONT_MEDIUM, multiline=False, max_lines=1):
        self.rect = pygame.Rect(x, y, width, height)
        self.color_inactive = GRAY
        self.color_active = BLUE
        self.color = self.color_inactive
        self.text = text
        self.placeholder = placeholder
        self.font = font
        self.active = False
        self.multiline = multiline
        self.max_lines = max_lines if not multiline else max_lines
        self.lines = [text]
        self.current_line = 0
        self.cursor_pos = len(text)
        self.cursor_visible = True
        self.cursor_timer = 0
        self.ime_text = ""
        self.ime_active = False
        self.last_key_time = 0
        self.ctrl_pressed = False

    def handle_event(self, event):
        current_time = pygame.time.get_ticks()
        
        # 检测鼠标点击
        if event.type == MOUSEBUTTONDOWN:
            was_active = self.active
            self.active = self.rect.collidepoint(event.pos)
            self.color = self.color_active if self.active else self.color_inactive
            
            # 激活或取消文本输入
            if self.active and not was_active:
                pygame.key.start_text_input()
                # 设置文本输入区域为输入框区域
                pygame.key.set_text_input_rect(self.rect)
            elif not self.active and was_active:
                # 如果有IME输入中的文本，提交它
                if self.ime_text:
                    current_line = self.lines[self.current_line]
                    self.lines[self.current_line] = current_line[:self.cursor_pos] + self.ime_text + current_line[self.cursor_pos:]
                    self.cursor_pos += len(self.ime_text)
                    self.ime_text = ""
                    self.ime_active = False
        
        # 检测Ctrl键的状态
        if event.type == KEYDOWN:
            if event.key == K_LCTRL or event.key == K_RCTRL:
                self.ctrl_pressed = True
        elif event.type == KEYUP:
            if event.key == K_LCTRL or event.key == K_RCTRL:
                self.ctrl_pressed = False
        
        # 处理文本编辑事件
        if event.type == KEYDOWN and self.active:
            # 如果有IME输入中的文本，先提交它
            if self.ime_active and event.key not in [K_RETURN, K_ESCAPE]:
                current_line = self.lines[self.current_line]
                self.lines[self.current_line] = current_line[:self.cursor_pos] + self.ime_text + current_line[self.cursor_pos:]
                self.cursor_pos += len(self.ime_text)
                self.ime_text = ""
                self.ime_active = False
            
            if event.key == K_RETURN and self.multiline and len(self.lines) < self.max_lines:
                # 在多行模式下添加新行
                current_line = self.lines[self.current_line]
                before_cursor = current_line[:self.cursor_pos]
                after_cursor = current_line[self.cursor_pos:]
                self.lines[self.current_line] = before_cursor
                self.lines.insert(self.current_line + 1, after_cursor)
                self.current_line += 1
                self.cursor_pos = 0
            elif event.key == K_BACKSPACE:
                if self.ime_text:
                    self.ime_text = self.ime_text[:-1]
                elif self.cursor_pos > 0:
                    current_line = self.lines[self.current_line]
                    self.lines[self.current_line] = current_line[:self.cursor_pos-1] + current_line[self.cursor_pos:]
                    self.cursor_pos -= 1
                elif self.current_line > 0 and self.multiline:
                    # 删除行并将光标移到上一行末尾
                    prev_line_len = len(self.lines[self.current_line - 1])
                    self.lines[self.current_line - 1] += self.lines[self.current_line]
                    self.lines.pop(self.current_line)
                    self.current_line -= 1
                    self.cursor_pos = prev_line_len
            elif event.key == K_DELETE:
                if self.ime_text:
                    self.ime_text = ""
                    self.ime_active = False
                else:
                    current_line = self.lines[self.current_line]
                    if self.cursor_pos < len(current_line):
                        self.lines[self.current_line] = current_line[:self.cursor_pos] + current_line[self.cursor_pos+1:]
                    elif self.current_line < len(self.lines) - 1 and self.multiline:
                        # 删除行尾并合并下一行
                        self.lines[self.current_line] += self.lines[self.current_line + 1]
                        self.lines.pop(self.current_line + 1)
            elif event.key == K_LEFT:
                if self.ime_text:
                    self.ime_text = ""
                    self.ime_active = False
                elif self.cursor_pos > 0:
                    self.cursor_pos -= 1
                elif self.current_line > 0 and self.multiline:
                    self.current_line -= 1
                    self.cursor_pos = len(self.lines[self.current_line])
            elif event.key == K_RIGHT:
                if self.ime_text:
                    current_line = self.lines[self.current_line]
                    self.lines[self.current_line] = current_line[:self.cursor_pos] + self.ime_text + current_line[self.cursor_pos:]
                    self.cursor_pos += len(self.ime_text)
                    self.ime_text = ""
                    self.ime_active = False
                else:
                    current_line = self.lines[self.current_line]
                    if self.cursor_pos < len(current_line):
                        self.cursor_pos += 1
                    elif self.current_line < len(self.lines) - 1 and self.multiline:
                        self.current_line += 1
                        self.cursor_pos = 0
            elif event.key == K_UP and self.multiline and self.current_line > 0:
                if self.ime_text:
                    self.ime_text = ""
                    self.ime_active = False
                self.current_line -= 1
                self.cursor_pos = min(self.cursor_pos, len(self.lines[self.current_line]))
            elif event.key == K_DOWN and self.multiline and self.current_line < len(self.lines) - 1:
                if self.ime_text:
                    self.ime_text = ""
                    self.ime_active = False
                self.current_line += 1
                self.cursor_pos = min(self.cursor_pos, len(self.lines[self.current_line]))
            elif event.key == K_ESCAPE:
                if self.ime_text:
                    self.ime_text = ""
                    self.ime_active = False
            elif event.unicode and event.unicode.isprintable():
                # 防止快速按键时重复输入
                if current_time - self.last_key_time > 10:  # 10毫秒防抖
                    current_line = self.lines[self.current_line]
                    self.lines[self.current_line] = current_line[:self.cursor_pos] + event.unicode + current_line[self.cursor_pos:]
                    self.cursor_pos += 1
                    self.last_key_time = current_time
            
            # 更新文本
            self.text = '\n'.join(self.lines)
            return True
        
        # 处理文本输入事件（支持IME输入法）
        elif event.type == pygame.TEXTINPUT and self.active:
            current_line = self.lines[self.current_line]
            # 直接插入文本，不使用IME缓冲区
            self.lines[self.current_line] = current_line[:self.cursor_pos] + event.text + current_line[self.cursor_pos:]
            self.cursor_pos += len(event.text)
            self.text = '\n'.join(self.lines)
            return True
        
        # 处理文本编辑事件（IME组合文本）
        elif event.type == pygame.TEXTEDITING and self.active:
            self.ime_text = event.text
            self.ime_active = len(event.text) > 0
            return True
            
        return False

    def draw(self, surface):
        # 绘制输入框背景
        pygame.draw.rect(surface, WHITE, self.rect, border_radius=5)
        pygame.draw.rect(surface, self.color, self.rect, 2, border_radius=5)
        
        # 绘制文本或占位符
        if self.text or self.ime_text or (self.active and self.cursor_visible):
            y_offset = self.rect.y + 5
            for i, line in enumerate(self.lines):
                if i == self.current_line and self.active:
                    # 当前行，需要绘制光标和IME文本
                    before_cursor = line[:self.cursor_pos]
                    txt_surface = self.font.render(before_cursor, True, BLACK)
                    surface.blit(txt_surface, (self.rect.x + 5, y_offset))
                    
                    # 绘制IME文本（如果有）
                    ime_x = self.rect.x + 5 + txt_surface.get_width()
                    if self.ime_text:
                        ime_surface = self.font.render(self.ime_text, True, BLUE)
                        surface.blit(ime_surface, (ime_x, y_offset))
                        
                        # 绘制IME文本下方的下划线
                        pygame.draw.line(surface, BLUE, 
                                        (ime_x, y_offset + self.font.get_height()),
                                        (ime_x + ime_surface.get_width(), y_offset + self.font.get_height()),
                                        1)
                    
                    # 绘制光标
                    if self.cursor_visible and not self.ime_active:
                        cursor_x = ime_x + (self.font.render(self.ime_text, True, BLACK).get_width() if self.ime_text else 0)
                        pygame.draw.line(surface, BLACK, 
                                        (cursor_x, y_offset + 2), 
                                        (cursor_x, y_offset + self.font.get_height() - 2), 2)
                    
                    # 绘制光标后的文本
                    after_cursor = line[self.cursor_pos:]
                    if after_cursor:
                        after_x = ime_x + (self.font.render(self.ime_text, True, BLACK).get_width() if self.ime_text else 0)
                        txt_surface = self.font.render(after_cursor, True, BLACK)
                        surface.blit(txt_surface, (after_x, y_offset))
                else:
                    # 非当前行，直接绘制
                    txt_surface = self.font.render(line, True, BLACK)
                    surface.blit(txt_surface, (self.rect.x + 5, y_offset))
                
                y_offset += self.font.get_height() + 2
        elif not self.active and self.placeholder:
            # 绘制占位符
            txt_surface = self.font.render(self.placeholder, True, DARK_GRAY)
            surface.blit(txt_surface, (self.rect.x + 5, self.rect.y + 5))
        
        # 更新光标闪烁
        self.cursor_timer += 1
        if self.cursor_timer > 30:  # 每30帧切换一次光标可见状态
            self.cursor_visible = not self.cursor_visible
            self.cursor_timer = 0

class Dropdown:
    def __init__(self, x, y, width, height, options, default_index=0, font=FONT_MEDIUM):
        self.rect = pygame.Rect(x, y, width, height)
        self.options = options
        self.selected_index = default_index
        self.font = font
        self.is_open = False
        self.option_rects = []
        self.update_option_rects()

    def update_option_rects(self):
        self.option_rects = []
        for i in range(len(self.options)):
            self.option_rects.append(pygame.Rect(
                self.rect.x, 
                self.rect.y + self.rect.height * (i + 1), 
                self.rect.width, 
                self.rect.height
            ))

    def draw(self, surface):
        # 绘制主框
        pygame.draw.rect(surface, WHITE, self.rect, border_radius=5)
        pygame.draw.rect(surface, GRAY, self.rect, 2, border_radius=5)
        
        # 绘制选中的选项
        text_surface = self.font.render(self.options[self.selected_index], True, BLACK)
        text_rect = text_surface.get_rect(midleft=(self.rect.x + 10, self.rect.centery))
        surface.blit(text_surface, text_rect)
        
        # 绘制下拉箭头
        arrow_points = [
            (self.rect.right - 20, self.rect.centery - 5),
            (self.rect.right - 10, self.rect.centery - 5),
            (self.rect.right - 15, self.rect.centery + 5)
        ]
        pygame.draw.polygon(surface, BLACK, arrow_points)
        
        # 如果下拉框打开，绘制选项
        if self.is_open:
            for i, option_rect in enumerate(self.option_rects):
                pygame.draw.rect(surface, WHITE, option_rect)
                pygame.draw.rect(surface, GRAY, option_rect, 1)
                
                text_surface = self.font.render(self.options[i], True, BLACK)
                text_rect = text_surface.get_rect(midleft=(option_rect.x + 10, option_rect.centery))
                surface.blit(text_surface, text_rect)

    def handle_event(self, event):
        if event.type == MOUSEBUTTONDOWN and event.button == 1:
            if self.rect.collidepoint(event.pos):
                self.is_open = not self.is_open
                return True
            elif self.is_open:
                for i, option_rect in enumerate(self.option_rects):
                    if option_rect.collidepoint(event.pos):
                        self.selected_index = i
                        self.is_open = False
                        return True
                self.is_open = False
        return False

    def get_selected(self):
        return self.options[self.selected_index]

    def get_selected_index(self):
        return self.selected_index

class DatePicker:
    def __init__(self, x, y, width, height, font=FONT_MEDIUM):
        self.rect = pygame.Rect(x, y, width, height)
        self.font = font
        self.date = datetime.date.today()
        self.is_open = False
        self.calendar_rect = pygame.Rect(x, y + height, width + 100, height * 8)
        self.day_rects = []
        self.month_buttons = [
            Button(x + 10, y + height + 10, 30, 30, "<", LIGHT_GRAY, GRAY),
            Button(x + width + 70, y + height + 10, 30, 30, ">", LIGHT_GRAY, GRAY)
        ]
        self.update_calendar()

    def update_calendar(self):
        self.day_rects = []
        year, month = self.date.year, self.date.month
        
        # 获取当月第一天是星期几
        first_day = datetime.date(year, month, 1).weekday()
        
        # 获取当月天数
        if month == 12:
            last_day = datetime.date(year + 1, 1, 1) - datetime.timedelta(days=1)
        else:
            last_day = datetime.date(year, month + 1, 1) - datetime.timedelta(days=1)
        days_in_month = last_day.day
        
        # 创建日历网格
        day_width = (self.calendar_rect.width - 20) // 7
        day_height = 30
        
        # 星期标题
        weekdays = ["一", "二", "三", "四", "五", "六", "日"]
        for i, day in enumerate(weekdays):
            x = self.calendar_rect.x + 10 + i * day_width
            y = self.calendar_rect.y + 50
            self.day_rects.append((pygame.Rect(x, y, day_width, day_height), 0, day))
        
        # 日期
        day = 1
        for week in range(6):  # 最多6周
            for weekday in range(7):
                if (week == 0 and weekday < first_day) or day > days_in_month:
                    continue
                
                x = self.calendar_rect.x + 10 + weekday * day_width
                y = self.calendar_rect.y + 50 + (week + 1) * day_height
                self.day_rects.append((pygame.Rect(x, y, day_width, day_height), day, str(day)))
                day += 1
                
                if day > days_in_month:
                    break

    def draw(self, surface):
        # 绘制主框
        pygame.draw.rect(surface, WHITE, self.rect, border_radius=5)
        pygame.draw.rect(surface, GRAY, self.rect, 2, border_radius=5)
        
        # 绘制日期文本
        date_str = self.date.strftime("%Y-%m-%d")
        text_surface = self.font.render(date_str, True, BLACK)
        text_rect = text_surface.get_rect(midleft=(self.rect.x + 10, self.rect.centery))
        surface.blit(text_surface, text_rect)
        
        # 绘制日历图标
        calendar_icon = [
            (self.rect.right - 25, self.rect.centery - 7),
            (self.rect.right - 15, self.rect.centery - 7),
            (self.rect.right - 15, self.rect.centery + 7),
            (self.rect.right - 25, self.rect.centery + 7)
        ]
        pygame.draw.polygon(surface, BLACK, calendar_icon, 1)
        
        # 如果日历打开，绘制日历
        if self.is_open:
            pygame.draw.rect(surface, WHITE, self.calendar_rect, border_radius=5)
            pygame.draw.rect(surface, GRAY, self.calendar_rect, 2, border_radius=5)
            
            # 绘制月份和年份
            month_year = self.date.strftime("%Y年%m月")
            text_surface = self.font.render(month_year, True, BLACK)
            text_rect = text_surface.get_rect(center=(self.calendar_rect.centerx, self.calendar_rect.y + 25))
            surface.blit(text_surface, text_rect)
            
            # 绘制月份切换按钮
            for button in self.month_buttons:
                button.draw(surface)
            
            # 绘制日期网格
            for rect, day, text in self.day_rects:
                if day == self.date.day and text.isdigit():
                    pygame.draw.rect(surface, LIGHT_BLUE, rect, border_radius=3)
                elif text.isdigit():
                    pygame.draw.rect(surface, LIGHT_GRAY, rect, border_radius=3)
                
                text_surface = self.font.render(text, True, BLACK)
                text_rect = text_surface.get_rect(center=rect.center)
                surface.blit(text_surface, text_rect)

    def handle_event(self, event):
        if event.type == MOUSEBUTTONDOWN and event.button == 1:
            if self.rect.collidepoint(event.pos):
                self.is_open = not self.is_open
                return True
            elif self.is_open:
                # 检查月份切换按钮
                for i, button in enumerate(self.month_buttons):
                    if button.is_clicked(event.pos, event):
                        if i == 0:  # 上个月
                            if self.date.month == 1:
                                self.date = self.date.replace(year=self.date.year - 1, month=12)
                            else:
                                self.date = self.date.replace(month=self.date.month - 1)
                        else:  # 下个月
                            if self.date.month == 12:
                                self.date = self.date.replace(year=self.date.year + 1, month=1)
                            else:
                                self.date = self.date.replace(month=self.date.month + 1)
                        self.update_calendar()
                        return True
                
                # 检查日期点击
                for rect, day, text in self.day_rects:
                    if rect.collidepoint(event.pos) and text.isdigit():
                        self.date = self.date.replace(day=int(text))
                        self.is_open = False
                        return True
                
                # 点击日历外部关闭日历
                if not self.calendar_rect.collidepoint(event.pos):
                    self.is_open = False
        return False

    def get_date(self):
        return self.date.strftime("%Y-%m-%d")

class Checkbox:
    def __init__(self, x, y, size, is_checked=False):
        self.rect = pygame.Rect(x, y, size, size)
        self.is_checked = is_checked
        self.size = size

    def draw(self, surface):
        pygame.draw.rect(surface, WHITE, self.rect, border_radius=3)
        pygame.draw.rect(surface, GRAY, self.rect, 2, border_radius=3)
        
        if self.is_checked:
            # 绘制勾选标记
            check_margin = self.size // 4
            pygame.draw.line(surface, GREEN, 
                            (self.rect.x + check_margin, self.rect.centery),
                            (self.rect.centerx - check_margin // 2, self.rect.y + self.size - check_margin),
                            3)
            pygame.draw.line(surface, GREEN, 
                            (self.rect.centerx - check_margin // 2, self.rect.y + self.size - check_margin),
                            (self.rect.x + self.size - check_margin, self.rect.y + check_margin),
                            3)

    def handle_event(self, event):
        if event.type == MOUSEBUTTONDOWN and event.button == 1:
            if self.rect.collidepoint(event.pos):
                self.is_checked = not self.is_checked
                return True
        return False

# 应用程序状态
class AppState:
    def __init__(self):
        self.current_view = "list"  # list, add, edit, detail
        self.tasks = []
        self.current_task = None
        self.sort_by = "priority"
        self.filter_completed = None
        self.scroll_offset = 0
        self.max_scroll = 0
        self.edit_task_id = None
        self.search_text = ""
        
        # UI组件
        self.init_ui_components()
        
    def init_ui_components(self):
        # 主视图按钮
        self.add_task_button = Button(SCREEN_WIDTH - 180, 20, 160, 40, "添加新任务", BLUE, LIGHT_BLUE, WHITE)
        
        # 排序和筛选按钮
        self.sort_buttons = [
            Button(20, 80, 120, 30, "按优先级排序", LIGHT_GRAY, GRAY),
            Button(150, 80, 120, 30, "按日期排序", LIGHT_GRAY, GRAY)
        ]
        
        self.filter_buttons = [
            Button(280, 80, 100, 30, "全部任务", LIGHT_GRAY, GRAY),
            Button(390, 80, 100, 30, "未完成", LIGHT_GRAY, GRAY),
            Button(500, 80, 100, 30, "已完成", LIGHT_GRAY, GRAY)
        ]
        
        # 搜索框
        self.search_box = InputBox(610, 80, 200, 30, "", "搜索任务...", FONT_MEDIUM)
        
        # 添加/编辑任务表单
        self.title_input = InputBox(150, 150, 400, 40, "", "任务标题", FONT_MEDIUM)
        self.description_input = InputBox(150, 220, 700, 120, "", "任务描述", FONT_MEDIUM, multiline=True, max_lines=5)
        self.due_date_picker = DatePicker(150, 370, 200, 40, FONT_MEDIUM)
        
        self.priority_dropdown = Dropdown(150, 440, 200, 40, ["高", "中", "低"], 2, FONT_MEDIUM)
        self.completed_checkbox = Checkbox(150, 510, 30)
        
        self.save_button = Button(150, 580, 120, 40, "保存", GREEN, (100, 220, 100), WHITE)
        self.cancel_button = Button(290, 580, 120, 40, "取消", LIGHT_GRAY, GRAY)
        self.delete_button = Button(730, 580, 120, 40, "删除", RED, (220, 50, 50), WHITE)

    def load_tasks(self):
        """从数据库加载任务"""
        self.tasks = get_all_tasks(self.sort_by, self.filter_completed)
        
        # 如果有搜索文本，过滤任务
        if self.search_text:
            search_lower = self.search_text.lower()
            self.tasks = [task for task in self.tasks if 
                         search_lower in task[1].lower() or  # 标题
                         (task[2] and search_lower in task[2].lower())]  # 描述
        
        # 计算最大滚动偏移
        task_height = 80
        total_height = len(self.tasks) * task_height
        visible_height = SCREEN_HEIGHT - 150  # 减去顶部区域高度，包括统计信息
        self.max_scroll = max(0, total_height - visible_height)

# 主应用程序
class TaskManager:
    def __init__(self):
        self.state = AppState()
        self.clock = pygame.time.Clock()
        self.running = True
        
        # 初始化数据库
        init_database()
        
        # 加载任务
        self.state.load_tasks()

    def run(self):
        while self.running:
            mouse_pos = pygame.mouse.get_pos()
            
            # 处理事件
            for event in pygame.event.get():
                if event.type == QUIT:
                    self.running = False
                
                self.handle_event(event, mouse_pos)
            
            # 更新屏幕
            self.draw()
            
            # 限制帧率
            self.clock.tick(60)
        
        pygame.quit()

    def handle_event(self, event, mouse_pos):
        # 通用按钮检查
        if self.state.current_view == "list":
            # 主视图按钮
            if self.state.add_task_button.is_clicked(mouse_pos, event):
                self.state.current_view = "add"
                self.state.title_input.text = ""
                self.state.description_input.text = ""
                self.state.description_input.lines = [""]
                self.state.due_date_picker.date = datetime.date.today()
                self.state.priority_dropdown.selected_index = 2
                self.state.completed_checkbox.is_checked = False
                return
            
            # 排序按钮
            for i, button in enumerate(self.state.sort_buttons):
                if button.is_clicked(mouse_pos, event):
                    if i == 0:
                        self.state.sort_by = "priority"
                    else:
                        self.state.sort_by = "due_date"
                    self.state.load_tasks()
                    return
            
            # 筛选按钮
            for i, button in enumerate(self.state.filter_buttons):
                if button.is_clicked(mouse_pos, event):
                    if i == 0:
                        self.state.filter_completed = None
                    elif i == 1:
                        self.state.filter_completed = 0
                    else:
                        self.state.filter_completed = 1
                    self.state.load_tasks()
                    return
            
            # 搜索框
            if self.state.search_box.handle_event(event):
                self.state.search_text = self.state.search_box.text
                self.state.load_tasks()
                return
            
            # 任务列表点击
            if event.type == MOUSEBUTTONDOWN:
                # 处理滚动
                if event.button == 4:  # 滚轮向上
                    self.state.scroll_offset = max(0, self.state.scroll_offset - 40)
                elif event.button == 5:  # 滚轮向下
                    self.state.scroll_offset = min(self.state.max_scroll, self.state.scroll_offset + 40)
                elif event.button == 1:  # 左键点击
                    # 检查是否点击了任务
                    task_height = 80
                    start_y = 150 - self.state.scroll_offset  # 修改起始位置，避免遮挡统计信息
                    
                    for i, task in enumerate(self.state.tasks):
                        task_rect = pygame.Rect(20, start_y + i * task_height, SCREEN_WIDTH - 40, task_height - 10)
                        
                        if task_rect.collidepoint(mouse_pos):
                            # 检查是否点击了完成状态复选框
                            checkbox_rect = pygame.Rect(task_rect.right - 40, task_rect.centery - 15, 30, 30)
                            
                            if checkbox_rect.collidepoint(mouse_pos):
                                # 切换任务完成状态
                                toggle_task_status(task[0], 1 if task[5] == 0 else 0)
                                self.state.load_tasks()
                            else:
                                # 打开任务详情
                                self.state.current_view = "edit"
                                self.state.edit_task_id = task[0]
                                self.state.title_input.text = task[1]
                                self.state.title_input.lines = [task[1]]
                                self.state.description_input.text = task[2] if task[2] else ""
                                self.state.description_input.lines = task[2].split('\n') if task[2] else [""]
                                
                                if task[3]:  # 截止日期
                                    try:
                                        year, month, day = map(int, task[3].split('-'))
                                        self.state.due_date_picker.date = datetime.date(year, month, day)
                                    except:
                                        self.state.due_date_picker.date = datetime.date.today()
                                else:
                                    self.state.due_date_picker.date = datetime.date.today()
                                
                                # 优先级 (1-高, 2-中, 3-低)
                                self.state.priority_dropdown.selected_index = task[4] - 1 if 1 <= task[4] <= 3 else 2
                                self.state.completed_checkbox.is_checked = task[5] == 1
                            return
        
        elif self.state.current_view in ["add", "edit"]:
            # 表单输入处理
            self.state.title_input.handle_event(event)
            self.state.description_input.handle_event(event)
            self.state.due_date_picker.handle_event(event)
            self.state.priority_dropdown.handle_event(event)
            self.state.completed_checkbox.handle_event(event)
            
            # 保存按钮
            if self.state.save_button.is_clicked(mouse_pos, event):
                title = self.state.title_input.text.strip()
                if not title:
                    return  # 标题不能为空
                
                description = self.state.description_input.text
                due_date = self.state.due_date_picker.get_date()
                priority = self.state.priority_dropdown.get_selected_index() + 1
                completed = 1 if self.state.completed_checkbox.is_checked else 0
                
                if self.state.current_view == "add":
                    add_task(title, description, due_date, priority)
                else:
                    update_task(self.state.edit_task_id, title, description, due_date, priority, completed)
                
                self.state.current_view = "list"
                self.state.load_tasks()
                return
            
            # 取消按钮
            if self.state.cancel_button.is_clicked(mouse_pos, event):
                self.state.current_view = "list"
                return
            
            # 删除按钮 (仅编辑模式)
            if self.state.current_view == "edit" and self.state.delete_button.is_clicked(mouse_pos, event):
                delete_task(self.state.edit_task_id)
                self.state.current_view = "list"
                self.state.load_tasks()
                return

    def draw(self):
        # 清空屏幕
        screen.fill(LIGHT_GRAY)
        
        # 绘制顶部标题栏
        pygame.draw.rect(screen, WHITE, (0, 0, SCREEN_WIDTH, 60))
        pygame.draw.line(screen, GRAY, (0, 60), (SCREEN_WIDTH, 60), 1)
        
        title_text = FONT_TITLE.render("个人任务管理器", True, BLACK)
        screen.blit(title_text, (20, 10))
        
        # 绘制当前日期
        current_date = datetime.date.today().strftime("%Y年%m月%d日")
        date_text = FONT_MEDIUM.render(current_date, True, DARK_GRAY)
        screen.blit(date_text, (SCREEN_WIDTH - date_text.get_width() - 20, 20))
        
        # 根据当前视图绘制不同内容
        if self.state.current_view == "list":
            self.draw_task_list()
        elif self.state.current_view in ["add", "edit"]:
            self.draw_task_form()
        
        # 更新显示
        pygame.display.flip()

    def draw_task_list(self):
        # 绘制添加任务按钮
        self.state.add_task_button.check_hover(pygame.mouse.get_pos())
        self.state.add_task_button.draw(screen)
        
        # 绘制排序和筛选按钮
        for i, button in enumerate(self.state.sort_buttons):
            button.check_hover(pygame.mouse.get_pos())
            if (i == 0 and self.state.sort_by == "priority") or (i == 1 and self.state.sort_by == "due_date"):
                button.color = BLUE
                button.hover_color = LIGHT_BLUE
                button.text_color = WHITE
            else:
                button.color = LIGHT_GRAY
                button.hover_color = GRAY
                button.text_color = BLACK
            button.draw(screen)
        
        for i, button in enumerate(self.state.filter_buttons):
            button.check_hover(pygame.mouse.get_pos())
            if (i == 0 and self.state.filter_completed is None) or \
               (i == 1 and self.state.filter_completed == 0) or \
               (i == 2 and self.state.filter_completed == 1):
                button.color = BLUE
                button.hover_color = LIGHT_BLUE
                button.text_color = WHITE
            else:
                button.color = LIGHT_GRAY
                button.hover_color = GRAY
                button.text_color = BLACK
            button.draw(screen)
        
        # 绘制搜索框
        self.state.search_box.draw(screen)
        
        # 绘制任务统计
        stats = get_task_stats()
        stats_text = f"总任务: {stats['total']} | 已完成: {stats['completed']} | 未完成: {stats['pending']} | 高优先级: {stats['high_priority']}"
        stats_surface = FONT_SMALL.render(stats_text, True, DARK_GRAY)
        screen.blit(stats_surface, (20, 120))
        
        # 创建一个任务列表区域的矩形，从统计信息下方开始
        task_list_rect = pygame.Rect(0, 150, SCREEN_WIDTH, SCREEN_HEIGHT - 150)
        pygame.draw.rect(screen, LIGHT_GRAY, task_list_rect)
        
        # 绘制任务列表
        task_height = 80
        start_y = 150 - self.state.scroll_offset  # 修改起始位置，避免遮挡统计信息
        
        for i, task in enumerate(self.state.tasks):
            task_y = start_y + i * task_height
            
            # 如果任务在可见区域外，跳过绘制
            if task_y + task_height < 150 or task_y > SCREEN_HEIGHT:
                continue
            
            # 任务卡片背景 - 增加高度以避免内容重叠
            task_rect = pygame.Rect(20, task_y, SCREEN_WIDTH - 40, task_height)
            pygame.draw.rect(screen, WHITE, task_rect, border_radius=10)
            
            # 优先级颜色条
            priority = task[4]
            priority_color = RED if priority == 1 else ORANGE if priority == 2 else GREEN
            pygame.draw.rect(screen, priority_color, (task_rect.x, task_rect.y, 10, task_rect.height), border_radius=5)
            
            # 任务标题
            title_text = FONT_MEDIUM.render(task[1], True, BLACK)
            screen.blit(title_text, (task_rect.x + 20, task_rect.y + 10))
            
            # 任务描述 (截断)
            description = task[2] if task[2] else ""
            if len(description) > 50:
                description = description[:50] + "..."
            desc_text = FONT_SMALL.render(description, True, DARK_GRAY)
            screen.blit(desc_text, (task_rect.x + 20, task_rect.y + 35))
            
            # 底部信息栏（截止日期和优先级）- 增加与描述的间距
            bottom_y = task_rect.y + task_rect.height - 22
            
            # 截止日期
            if task[3]:
                date_text = FONT_SMALL.render(f"截止日期: {task[3]}", True, DARK_GRAY)
                screen.blit(date_text, (task_rect.x + 20, bottom_y))
                
                # 计算优先级文本的位置，确保不会与日期重叠
                date_width = date_text.get_width()
                priority_x = task_rect.x + 40 + date_width
            else:
                priority_x = task_rect.x + 20
            
            # 优先级文本
            priority_text = ["高", "中", "低"][priority - 1]
            priority_surface = FONT_SMALL.render(f"优先级: {priority_text}", True, priority_color)
            screen.blit(priority_surface, (priority_x + 30, bottom_y))
            
            # 完成状态复选框
            checkbox_rect = pygame.Rect(task_rect.right - 40, task_rect.centery - 15, 30, 30)
            pygame.draw.rect(screen, WHITE, checkbox_rect, border_radius=5)
            pygame.draw.rect(screen, GRAY, checkbox_rect, 2, border_radius=5)
            
            if task[5] == 1:  # 已完成
                # 绘制勾选标记
                check_margin = 7
                pygame.draw.line(screen, GREEN, 
                                (checkbox_rect.x + check_margin, checkbox_rect.centery),
                                (checkbox_rect.centerx - check_margin // 2, checkbox_rect.y + checkbox_rect.height - check_margin),
                                3)
                pygame.draw.line(screen, GREEN, 
                                (checkbox_rect.centerx - check_margin // 2, checkbox_rect.y + checkbox_rect.height - check_margin),
                                (checkbox_rect.x + checkbox_rect.width - check_margin, checkbox_rect.y + check_margin),
                                3)
                
                # 已完成任务标题添加删除线
                pygame.draw.line(screen, DARK_GRAY, 
                               (task_rect.x + 20, task_rect.y + 20),
                               (task_rect.x + 20 + title_text.get_width(), task_rect.y + 20),
                               2)

    def draw_task_form(self):
        # 绘制表单标题
        title = "添加新任务" if self.state.current_view == "add" else "编辑任务"
        title_text = FONT_LARGE.render(title, True, BLACK)
        screen.blit(title_text, (20, 80))
        
        # 绘制表单字段标签
        field_labels = [
            ("标题:", 150, 130),
            ("描述:", 150, 200),
            ("截止日期:", 150, 350),
            ("优先级:", 150, 420),
            ("已完成:", 150, 510)  # 修改位置，确保标签可见
        ]
        
        for label, x, y in field_labels:
            label_text = FONT_MEDIUM.render(label, True, BLACK)
            screen.blit(label_text, (x - label_text.get_width() - 10, y))
        
        # 绘制表单输入控件
        self.state.title_input.draw(screen)
        self.state.description_input.draw(screen)
        self.state.due_date_picker.draw(screen)
        self.state.priority_dropdown.draw(screen)
        self.state.completed_checkbox.draw(screen)
        
        # 绘制按钮
        self.state.save_button.check_hover(pygame.mouse.get_pos())
        self.state.save_button.draw(screen)
        
        self.state.cancel_button.check_hover(pygame.mouse.get_pos())
        self.state.cancel_button.draw(screen)
        
        if self.state.current_view == "edit":
            self.state.delete_button.check_hover(pygame.mouse.get_pos())
            self.state.delete_button.draw(screen)

# 启动应用程序
if __name__ == "__main__":
    # 设置环境变量以支持中文输入
    if sys.platform.startswith('win'):
        # Windows系统
        os.environ['SDL_VIDEODRIVER'] = 'windib'
    
    app = TaskManager()
    app.run()
